home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
atan2bug.zip
/
ATAN2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-28
|
1KB
|
61 lines
/*
* This is an unofficial patch for Turbo C's atan2() function.
*
* It fixes the erratic behavior of the atan2() function at the
* coordinate axes. It's a little cryptic, but should be as fast
* as the original. Works with all the memory models, with or
* without a math coprocessor.
*
* Bugs: Doesn't screen x or y for NaN. Denormals are not distin-
* guished from zero.
*/
#include <math.h>
#include <values.h>
/*
* These #defines only work for IEEE 8-byte reals.
*/
#define DOUBLE_EXP_MASK 0x7FF0
#define DOUBLE_SIGN_MASK 0x8000
#define SIGNED(x) (((short *)(&x))[3] & DOUBLE_SIGN_MASK)
#define EXPONENT(x) (((short *)(&x))[3] & DOUBLE_EXP_MASK)
extern int errno;
static const unsigned long QNaN[2] = { 0xFFFFFFFFL, 0x7FFFFFFFL };
double atan2(double y, double x)
{
short exp_x = EXPONENT(x), exp_y = EXPONENT(y);
if (exp_x | exp_y) /* if x and y are not both zero */
{
double z;
short signed_x;
short domain = exp_x && (exp_y - exp_x < DMAXPOWTWO << 4);
if (domain) /* If it's OK to divide y by x */
{
z = atan(y/x);
signed_x = SIGNED(x);
}
if (SIGNED(y)) /* Sort out the quadrants... */
{
if (domain)
return signed_x ? z - M_PI : z;
else
return -M_PI_2;
}
else
{
if (domain)
return signed_x ? z + M_PI : z;
else
return M_PI_2;
}
}
errno = EDOM;
return *(double *)QNaN;
}